﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Reflection;
using System.Web.UI.WebControls;
using System.Collections;
using System.Web.UI.HtmlControls;
using Deeper.Common;
using Deeper.DataAccess;
using System.Web;


namespace Deeper.Common.Web
{
	public static class WebStringHelper
	{

		#region 字符串编码解码
		/// <summary>
		/// 返回 HTML 字符串的编码结果
		/// </summary>
		/// <param name="str">字符串</param>
		/// <returns>编码结果</returns>
		public static string HtmlEncode(this string str)
		{
			return HttpUtility.HtmlEncode(str);
		}

		/// <summary>
		/// 返回 HTML 字符串的解码结果
		/// </summary>
		/// <param name="str">字符串</param>
		/// <returns>解码结果</returns>
		public static string HtmlDecode(this string str)
		{
			return HttpUtility.HtmlDecode(str);
		}

		/// <summary>
		/// 返回 URL 字符串的编码结果
		/// </summary>
		/// <param name="str">字符串</param>
		/// <returns>编码结果</returns>
		public static string UrlEncode(this string str)
		{
			return HttpUtility.UrlEncode(str);
		}

		/// <summary>
		/// 返回 URL 字符串的编码结果
		/// </summary>
		/// <param name="str">字符串</param>
		/// <returns>解码结果</returns>
		public static string UrlDecode(this string str)
		{
			return HttpUtility.UrlDecode(str);
		}
		#endregion

		/// <summary>
		/// 从ViewState获取对象
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="ViewState"></param>
		/// <param name="name"></param>
		/// <param name="objDefault"></param>
		/// <returns></returns>
		public static T GetFromViewState<T>(this StateBag ViewState, string name, T objDefault)
		{
			if (null != ViewState[name])
				return (T)ViewState[name];
			else
				return objDefault;
		}

		public static object PageBind<TEntity>(this System.Web.UI.Page p, Func<TEntity, object> func, string format = null)
		{
			var dataItem = p.GetDataItem();
			if (dataItem.IsNull()) return "";
			if (format.IsNull())
				return func((TEntity)dataItem);
			else
				return string.Format(format, func((TEntity)dataItem));
		}



		/// <summary>
		/// 执行事件
		/// </summary>
		/// <param name="ActionName"></param>
		/// <param name="act"></param>
		/// <param name="IsShowMessage"></param>
		/// <param name="isTrans"></param>
		public static void InfoAction(this string ActionName, Action act, bool IsShowMessage = true, bool isTrans = false)
		{
			try
			{
				if (isTrans) HDbHelper.Transaction(act);
				else act();
				if (IsShowMessage)
					MessageBox.Show(ActionName + "成功", true);
			}
			catch (DeeperException de)
			{
				if (IsShowMessage)
					MessageBox.Show(de.Message, true, type: "confirm");
				LogHelper.WriteLog(ActionName + "发生错误:\r\n" + de.Message);
			}
			catch (Exception ex)
			{
				if (IsShowMessage)
					MessageBox.Show(ActionName + "失败,错误原因:" + ex.Message, true, type: "confirm");
				LogHelper.WriteLog(ActionName + "发生错误:\r\n" + ex.Message);
			}
		}
	}
	public static class ControlExtions
	{

		/// <summary>
		/// 绑定ListControl
		/// </summary>
		/// <param name="ctrl">要绑定的控件</param>
		/// <param name="list">数据源IList或者datatable</param>
		/// <param name="dataTextField">显示属性名称</param>
		/// <param name="dataValueField">值属性名称</param>
		/// <param name="defaultText">自定义显示文版</param>
		/// <param name="defaultValue">自定义显示值</param>
		public static void BindList(this ListControl ctrl, object list, string dataTextField, string dataValueField, string defaultText = "", string defaultValue = "")
		{
			ctrl.Items.Clear();
			ctrl.DataSource = list;
			ctrl.DataTextField = dataTextField;
			ctrl.DataValueField = dataValueField;
			ctrl.DataBind();
			if (!defaultText.IsNull())
			{
				ListItem defaultItem = new ListItem(defaultText, defaultValue);
				defaultItem.Selected = true;
				ctrl.Items.Insert(0, defaultItem);
			}
		}

		/// <summary>
		/// 递归查找找指定ID的控件
		/// </summary>
		/// <param name="Parent">父控件(控件容器)</param>
		/// <param name="id">要查找的控件ID</param>
		/// <returns>回传符合ID的控件，若未找到则返回Null</returns>
		public static Control FindControlEx(System.Web.UI.Control Parent, string id)
		{
			System.Web.UI.Control oCtrl = null;
			//先使用 FindControl 去查找指定的子控件
			oCtrl = Parent.FindControl(id);

			//如果未找到则往下层递归方式去查找
			if (oCtrl == null)
			{
				foreach (System.Web.UI.Control oChildCtrl in Parent.Controls)
				{
					//以递归方式回调原函数
					oCtrl = FindControlEx(oChildCtrl, id);
					//如果找到指定控件则退出循环
					if (oCtrl != null) break;
				}
			}
			return oCtrl;
		}

		public static void FindControlAll(this Control parent, IList<Control> list)
		{
			foreach (Control ctrl in parent.Controls)
			{
				if (ctrl.HasControls())
				{
					ctrl.FindControlAll(list);
				}
				if (ctrl is ITextControl || ctrl is ListControl || ctrl is ICheckBoxControl || ctrl is HtmlInputControl || ctrl is HiddenField || ctrl is Image || ctrl is Button)
				{
					if (!ctrl.ID.IsNull())
						list.Add(ctrl);
				}
			}
		}


	}

	/// <summary>
	/// 控件与实体之间的绑定，控件命名规则是前缀+字段名，字段名只有首字母能大写
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public static class FormHelper//<T> where T : class, new()
	{

		#region 绑定控件

		#region 找控件
		/// <summary>
		/// 检测名称是否匹配
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="ctrlId"></param>
		/// <param name="tableAlias"></param>
		/// <param name="ctrlNameType"></param>
		/// <returns></returns>
		public static bool IsMatchName(string propertyName, string ctrlId)
		{
			bool isMatch = false;
			int pos = ctrlId.IndexOf(propertyName[0].ToString().ToUpper());
			if (pos > 0)
				isMatch = ctrlId.Substring(pos, ctrlId.Length - pos).ToLower().Equals(propertyName.ToLower());
			return isMatch;
		}


		private static Control GetMatchedControl(PropertyInfo hattr, IEnumerable<Control> ctrlLists)
		{
			IList<string> strlist = new List<string>();
			ctrlLists.ToList().ForEach(s => strlist.Add(s.ID));
			return ctrlLists.ToList().Find<Control>(s => IsMatchName(hattr.Name, s.ID));
		}
		#endregion

		#region 从控件获取值
		/// <summary>
		/// 从控件获取值
		/// </summary>
		/// <param name="t"></param>
		/// <param name="hattr"></param>

		/// <param name="ctrlLists"></param>
		/// <param name="ctrlNameType"></param>
		/// <param name="tableAlias"></param>
		private static void GetValueFromCtrl(object t, PropertyInfo hattr, IEnumerable<Control> ctrlLists)
		{
			try
			{
				Control ctrl = GetMatchedControl(hattr, ctrlLists);

				if (ctrl.IsNull()) return;
				bool IsNullable = Nullable.GetUnderlyingType(hattr.PropertyType).IsNotNull();
				if (!(hattr.PropertyType.IsPrimitive || (hattr.PropertyType.Name == "String") || IsNullable)) return;

				if (ctrl is ListControl)
				{
					if (((ListControl)ctrl).SelectedItem != null)
						hattr.SetValue(t, ((ListControl)ctrl).SelectedValue.ChangeType(hattr.PropertyType), null);
					else if (IsNullable)
						hattr.SetValue(t, null, null);
				}
				else if (ctrl is ITextControl)
				{
					if (!((ITextControl)ctrl).Text.Trim().IsNull())
						hattr.SetValue(t, ((ITextControl)ctrl).Text.ChangeType(hattr.PropertyType), null);
					else if (IsNullable)
						hattr.SetValue(t, null, null);
				}
				else if (ctrl is HtmlInputHidden)
				{
					if (!((HtmlInputHidden)ctrl).Value.IsNull())
						hattr.SetValue(t, ((HtmlInputHidden)ctrl).Value.ChangeType(hattr.PropertyType), null);
					else if (IsNullable)
						hattr.SetValue(t, null, null);
				}
				else if (ctrl is HiddenField)
				{
					if (!((HiddenField)ctrl).Value.IsNull())
						hattr.SetValue(t, ((HiddenField)ctrl).Value.ChangeType(hattr.PropertyType), null);
					else if (IsNullable)
						hattr.SetValue(t, null, null);
				}
				else if (ctrl is ICheckBoxControl)
				{
					hattr.SetValue(t, ((ICheckBoxControl)ctrl).Checked, null);
				}
				else if (ctrl is HtmlInputCheckBox)
				{
					hattr.SetValue(t, ((HtmlInputCheckBox)ctrl).Checked, null);
				}
				else if (ctrl is HtmlInputRadioButton)
				{
					hattr.SetValue(t, ((HtmlInputRadioButton)ctrl).Checked, null);
				}
				else if (ctrl is Image)
				{
					hattr.SetValue(t, ((Image)ctrl).ImageUrl, null);
				}

			}
			catch (Exception ex)
			{
				throw new DeeperException(string.Format("{0}类的{1}字段赋值到控件出错", t.GetType().ToString(), hattr.Name), ex);
			}
		}

		/// <summary>
		/// 从控件取值到实体类
		/// </summary>
		/// <param name="t"></param>
		/// <param name="ctrlRoot"></param>
		/// <param name="ctrlNameType"></param>
		/// <param name="tableAlias"></param>
		public static void GetData(this object t, Control ctrlRoot)
		{
			IList<Control> list = new List<Control>();
			ctrlRoot.FindControlAll(list);

			List<PropertyInfo> plist = GetPropertyInfosWithCache(t);
			plist.ForEach(c => GetValueFromCtrl(t, c, list));
		}
		#endregion

		#region 赋值到控件
		/// <summary>
		/// 将实体类的字段赋值到控件
		/// </summary>
		/// <param name="t"></param>
		/// <param name="hattr"></param>
		/// <param name="ctrlList"></param>
		/// <param name="ctrlNameType"></param>
		/// <param name="tableAlias"></param>
		private static void SetValueToCtrl(object t, PropertyInfo hattr, IEnumerable<Control> ctrlList)
		{
			try
			{
				Control ctrl = GetMatchedControl(hattr, ctrlList);
				if (ctrl.IsNull()) return;
				object obj = hattr.GetValue(t, null);
				if (ctrl is ListControl)
				{
					ListItemCollection ls = ((ListControl)ctrl).Items;
					if (!obj.IsNull())
					{
						((ListControl)ctrl).SelectedIndex = ls.IndexOf(ls.FindByValue(obj.ToString()));
					}
					else
					{
						((ListControl)ctrl).SelectedIndex = ls.Count > 0 ? 0 : -1;
					}
				}
				else if (ctrl is ITextControl)
				{
					if (!obj.IsNull())
					{
						if (obj is DateTime)
							((ITextControl)ctrl).Text = ((DateTime)obj).ToString("yyyy-MM-dd");
						else if (obj is DateTime?)
							((ITextControl)ctrl).Text = ((DateTime?)obj).IsNull() ? "" : ((DateTime?)obj).Value.ToString("yyyy-MM-dd");
						else
							((ITextControl)ctrl).Text = obj.ToString();
					}
					else
						((ITextControl)ctrl).Text = "";
				}
				else if (ctrl is ICheckBoxControl)
				{
					if (!obj.IsNull())
						((ICheckBoxControl)ctrl).Checked = (bool)obj;
					else
						((ICheckBoxControl)ctrl).Checked = false;
				}
				else if (ctrl is HtmlInputHidden)
				{
					if (!obj.IsNull())
						((HtmlInputHidden)ctrl).Value = obj.ToString();
					else
						((HtmlInputHidden)ctrl).Value = "";
				}
				else if (ctrl is HiddenField)
				{
					if (!obj.IsNull())
						((HiddenField)ctrl).Value = obj.ToString();
					else
						((HiddenField)ctrl).Value = "";
				}

				else if (ctrl is HtmlInputCheckBox)
				{
					if (!obj.IsNull())
						((HtmlInputCheckBox)ctrl).Checked = (bool)obj;
				}
				else if (ctrl is HtmlInputRadioButton)
				{
					if (!obj.IsNull())
						((HtmlInputRadioButton)ctrl).Checked = (bool)obj;
				}
				else if (ctrl is Image)
				{
					if (!obj.IsNull() && obj is string)
						((Image)ctrl).ImageUrl = obj.ToString();
				}
			}
			catch
			{

			}
		}

		/// <summary>
		/// 赋值到控件
		/// </summary>
		/// <param name="t"></param>
		/// <param name="ctrlRoot"></param>
		/// <param name="ctrlNameType"></param>
		/// <param name="tableAlias"></param>
		public static void SetData(this object t, Control ctrlRoot)
		{
			IList<Control> list = new List<Control>();
			ctrlRoot.FindControlAll(list);

			List<PropertyInfo> plist = GetPropertyInfosWithCache(t);
			plist.ForEach(c => SetValueToCtrl(t, c, list));


		}

		/// <summary>
		/// 获取字段属性
		/// </summary>
		/// <param name="t"></param>
		/// <returns></returns>
		private static List<PropertyInfo> GetPropertyInfosWithCache(object t)
		{
			string CacheName = "Type_" + t.GetType().ToString();
			List<PropertyInfo> plist = CacheName.GetCache() as List<PropertyInfo>;
			if (plist.IsNull() || plist.Count == 0)
			{
				plist = new List<PropertyInfo>();
				plist.AddRange(t.GetType().GetProperties().ToList());
				CacheName.SetCache(plist);
			}
			return plist;
		}

		#endregion

		#endregion

	}
}
